<?php
/**
 * 当前项目的应用执行脚本
 * @author  ZhouHaoHua <53027327@qq.com>
 * @package
 */
class Application extends \core\models\Application {
    /**
     * 控制器的代表参数名
     * @var string
     */
    public $arg_controller_name = 'mod';
    /**
     * 动作方法的代表参数名
     * @var string
     */
    public $arg_action_name = 'action';
    /**
     * 运行程序
     */
    public function run() {
        $this->serversSet();
        //url路由处理
        $U = new \Url();
        $U->parseUrl();
        //控制器执行
        $this->runController();
        //视图处理
        $this->runView();
    }
    /**
     * 服务器变量统一调整
     */
    protected function serversSet() {
        //整合Apache与Nginx服务器变量。
        $_SERVER['REQUEST_URI'] = isset($_SERVER['HTTP_REQUEST_URI']) ? $_SERVER['HTTP_REQUEST_URI'] : $_SERVER['REQUEST_URI'];
    }
    /**
     * 执行视图处理输出
     */
    public function runView()
    {
        //发送heaer标记
        /*header('Content-type: text/html; charset='. Z_CHARSET_PROJECT);
        header('Access-Control-Allow-Origin: *');
        header('Access-Control-Allow-Methods: GET, POST, PUT, DELETE');
        header('Access-Control-Allow-Headers: Origin, X-Requested-With, Content-Type, Accept');
        header('Access-Control-Allow-Credentials:true');*/
        //echo Z_CHARSET_PROJECT;exit;
        $c = $this->controller;
        $this->data = $c->data;
        if($c->USE_PAGE_CACHE === false) {  // 禁止客户端缓存，如：浏览器缓存
            header("Expires: Mon, 26 Jul 1970 05:00:00 GMT");
            header("Last-Modified:" . gmdate("D,d M Y H:i:s") . "GMT ");
            header("Cache-Control: no-cache, must-revalidate");
            header("Pragma: no-cache");
        }
        /**
         * 视图文件夹路径
         * @var /home/html/zf/z/partner.usitrip.com/views/pc
         */
        $viewsPath = Z_APP . '/views/' . Z_TPL_VERSION;
        if ($c->data) {
            $errors = error_get_last();
            if (!$errors) {
                $gzip = new \core\models\Gzip();
                $gzip->ob_start();
            }

            $content_type = isset($_SERVER['CONTENT_TYPE']) ? $_SERVER['CONTENT_TYPE'] : $_SERVER['HTTP_ACCEPT'];
            //echo $content_type;exit;
            // 输出json或xml格式的数据
            $out_html = false;
            switch (1) {
                case \config_web::API_OUT_TYPE == 'json':
                //case strpos($content_type, 'application/json') !== false:
                    header("Content-Type: application/json; charset=utf-8");
                    echo json_encode($this->data, JSON_UNESCAPED_UNICODE); // 注意data数据必须是utf-8编码，否则异常或一息空白
                    break;
                case \config_web::API_OUT_TYPE == 'xml':
                //case strpos($content_type, 'application/xml') !== false:
                    header("Content-Type: application/xml");
                    echo \Z::Arrays()->toXml($this->data);
                    break;
                default:
                    $out_html = true;
                    break;
            }

            if ($out_html === true) {
                if ($c->tplTop || $c->tplContent || $c->tplBottom) {
                    $metaArr = array();
                    $html = new \Html('zh_CN', $c->metaCharset);
                    $html->title = $c->metaTitle;
                    $html->description = $c->metaDescription;
                    $html->keywords = $c->metaKeywords;
                    $ZV = Z::Views();
                    /**
                     * 网页头部的模板相关的模板tpl、js、css、image等组成的数组
                     * @var array
                     */
                    $tops = $ZV->getNewPath($viewsPath . '/MainPage/' . $c->tplTop);
                    $html->tplTop = $tops['tpl'];
                    $this->data['top']['path'] = realpath($html->tplTop);
                    /**
                     * 网页中间部分的模板相关的模板tpl、js、css、image等组成的数组
                     * @var array
                     */
                    $cons = $ZV->getNewPath($viewsPath . '/' . $c->tplContent);
                    $html->tplContent = $cons['tpl'];
                    $this->data['contentPath'] = realpath($html->tplContent);
                    /**
                     * 网页底部的模板相关的模板tpl、js、css、image等组成的数组
                     * @var array
                     */
                    $bots = $ZV->getNewPath($viewsPath . '/MainPage/' . $c->tplBottom);
                    $html->tplBottom = $bots['tpl'];
                    $this->data['bottom']['path'] = realpath($html->tplBottom);

                    $html->tplBodyExt = $c->tplBodyExt;
                    //按规则自动设置JS和CSS
                    if ($c->tplContent) {
                        $fCSS = $topJS = $footJS = array();
                        //$fCSS[] = '/' . Z_TOP_WWW . '/views/css/reset.css';
                        //$fCSS[] = '/' . Z_TOP_WWW . '/views/css/common.css';
                        //unset($fCSS);
                        /*$topJS[] = '/' . Z_TOP_WWW . '/views/js/sea.js';
                        $topJS[] = '/ext/jquery/jquery-1.12.0.min.js';
                        $topJS[] = '/ext/avalon/avalon.js';
                        $topJS[] = '/ext/bootstrap/js/bootstrap.min.js';
                        $topJS[] = '';*/

                        //$footJS[] = '/' . Z_TOP_WWW . '/views/js/js/sea.js';
                        //unset($topJS, $footJS);
                        $public_name = str_replace($viewsPath, '', preg_replace('@.tpl.php|.html$@', '', $html->tplContent));
                        /**
                         * 载入额外的CSS和JS文件
                         */
                        $moreJsCss = array();
                        $css_js_conf = $cons['conf'];
                        $fArray = array();
                        if (file_exists($css_js_conf)) {
                            $fArray = array_filter(preg_replace('@^#.+@', '', Z::Arrays()->trim(file($css_js_conf))));
                        }
                        if ($fArray) {
                            foreach ($fArray as $v) {
                                preg_match('/^([^\=]+)\=([^$]*)/', $v, $matches);
                                $_array = Z::Arrays()->trim($matches);
                                if ($_array[1] && $_array[2]) {
                                    $moreJsCss[$_array[1]] = $_array[2];
                                }
                            }
                        }
                        if ($moreJsCss) {
                            if ($moreJsCss['CSS']) {
                                $fCSS = array_merge((array)$fCSS, $this->setMoreJsCss($moreJsCss['CSS'], $viewsPath, 'css'));
                            }
                            if ($moreJsCss['HEAD_JS']) {
                                $topJS = array_merge((array)$topJS, $this->setMoreJsCss($moreJsCss['HEAD_JS'], $viewsPath, 'js'));
                            }
                            if ($moreJsCss['FOOT_JS']) {
                                $footJS = array_merge((array)$footJS, $this->setMoreJsCss($moreJsCss['FOOT_JS'], $viewsPath, 'js'));
                            }
                            IF ($moreJsCss['META']) {
                                $metaArr = array_merge((array)$metaArr, explode(',', $moreJsCss['META']));
                            }
                        }
                        $html->setMeta($metaArr);
                        $html->setCss($fCSS);
                        //载入与模板同名的CSS文件
                        $current_default_css = $cons['css'];
                        if (file_exists($current_default_css)) {
                            $html->setCss(preg_replace('@^' . preg_quote(Z_APP, '@') . '@', '', $current_default_css));
                        }
                        //载入额外的头部底部JS文件
                        if ($topJS) {
                            $html->setTopScript($topJS);
                        }
                        if ($footJS) {
                            $html->setBottomScript($footJS);
                        }
                        //载入与模板同名的JS文件到时【页面底部】
                        $current_default_js = $cons['js'];
                        if (file_exists($current_default_js)) {
                            $html->setBottomScript(preg_replace('@^' . preg_quote(Z_APP, '@') . '@', '', $current_default_js));
                        }
                    }
                    //输出编码转换
                    if (strtolower($c->dataCharset) != strtolower($c->metaCharset)) {
                        $this->data = \Z::Arrays()->iconv($c->dataCharset, $c->metaCharset, $this->data);
                    }

                    if (config::SMARTY_SWITCH === true) { //使用smarty模板  Z_SMARTY_SWITCH
                        /**
                         * 该变量在$c->tplMainPage模板文件中会用到
                         */
                        $smarty = $this->smartySet();
                    }
                    $MP = $ZV->getNewPath($viewsPath . '/' . $c->tplMainPage);
                    if (file_exists($MP['tpl'])) {
                        $this->data['tplMainPage'] = realpath($MP['tpl']);
                        require $MP['tpl'];
                    } else {
                        exit('not find ' . $MP['tpl']);
                    }
                } else {
                    //不设置任何模板时的数据处理
                    print_r($this->data);
                }
            }
            if ($c->htmlCache === true && $this->config->web()->htmlCacheSwitch === true) {
                $h = ob_get_contents();
                \PageStatic::createHtml($h, $c->tplContent, $c->htmlCache);
            }
            if (!$errors) {
                $gzip->ob_output();
            }
        }


    }

    private function setMoreJsCss($moreJsCss, $viewsPath, $type) {
        $fCSS = array();
        if ($moreJsCss) {
            $_arr = Z::Arrays()->trim(explode(',', $moreJsCss));
            foreach ($_arr as $_k => $_v) {
                if (basename($_v) == $_v && isset($_dir_file[$_k - 1])) {// 后面的文件若无指定路径则会取前一个文件的路径作为后面文件的所在路径如：/ext/bootstrap/css/1.css, 2.css, tmp/My/t.css。2.css和1.css的路径相同都属于/ext/bootstrap/css下面的文件！
                    $_dir_file[$_k] = dirname($_dir_file[$_k - 1]) . '/' . $_v;
                } else {
                    $_dir_file[$_k] = (strpos($_v, '/') === 0 ? $_v : preg_replace('@^' . preg_quote(Z_APP, '@') . '@', '', $viewsPath) . '/' . $type . '/' . $_v);
                }
                $fCSS[] = $_dir_file[$_k];
            }
        }
        return $fCSS;
    }

    /**
     * smarty模板相关设置
     */
    private function smartySet() {
        require(Z_SMARTY_LIBS . '/Smarty.class.php');
        $smarty = new Smarty();

        $smarty->template_dir = Z_SMARTY_TEMPLATE_DIR;
        $smarty->compile_dir  = Z_SMARTY_COMPILE_DIR;

        if (!is_writable($smarty->compile_dir)) {
            echo $smarty->compile_dir . " Write Failure! Please check it's Write Permissions!";
            exit;
        }
        if (config::DEBUG === true) {//Z_DEBUG
            $smarty->clear_compiled_tpl(); //删除tpl_c中的模板文件，在生产站时不要用此动作
        }
        $smarty->left_delimiter  = Z_SMARTY_DELIMITER_LEFT;//'{{';
        $smarty->right_delimiter = Z_SMARTY_DELIMITER_RIGHT;//'}}';
        //$smarty->php_handling    = SMARTY_PHP_ALLOW; //允许模板页里执行PHP代码
        $smarty->caching        = false; //启用缓存否【绝对不要开启，产品列表那里会有问题的。我们不用smarty的缓存！】
        $smarty->cache_lifetime = 3600; //缓存1小时
        $smarty->cache_dir      = _SMARTY_TPLC_ . 'cache'; //缓存保存目录

        if ($smarty->caching === true && !file_exists($smarty->cache_dir)) {  //创建缓存目录
            mkdir($smarty->cache_dir, 0700);
        }

        return $smarty;
    }

    /**
     * 404 处理
     * 注意：一般情况下在(new \Url())->parseUrl();中已经处理了各个页面的路由关系，此处就处理404即可！
     */
    public function notFound($e) {
        header("HTTP/1.1 404 Not Found");
        header("Status: 404 Not Found");
        //die($REQUEST_URI.'子控制器的404处理！');
        $_POST[$this->arg_controller_name] = 'page404';
        $_POST[$this->arg_action_name]     = 'index';
        $this->runController();
    }
}